package com.microservice.core.redis.configure;

import com.microservice.core.redis.properties.RedisConfigProperties;
import jakarta.annotation.Resource;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.cache.annotation.CachingConfigurer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * redis配置
 */
@Configuration
@EnableCaching
@AutoConfigureBefore(RedisAutoConfiguration.class)
public class RedisConfig implements CachingConfigurer {

    @Resource
    private RedisConfigProperties redisConfigProperties;

    @Bean
    @SuppressWarnings(value = {"unchecked", "rawtypes"})
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);

        FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);

        // 使用StringRedisSerializer来序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(serializer);

        // Hash的key也采用StringRedisSerializer的序列化方式
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(serializer);

        template.afterPropertiesSet();
        return template;
    }

    /**
     * 配置redis连接工厂
     * 常用的有两种
     * JedisConnectionFactory：Jedis 是单线程的,高并发下可能会成为瓶颈
     * LettuceConnectionFactory：Lettuce 是多线程的基于netty的异步客户端，线程安全，性能更好
     * springboot2.0以上默认使用Lettuce，可以不用配置以下内容，但是配置了,必须传入端口号，密码等参数
     * 这里没有配置redis用户名了,只设置了密码
     * 注意当你不使用下面手动设置redis配置时,则你的redis配置的yml格式如下,不管是配置在nacos中还是配置在resources目录
     * 下bootstrap.yml,都需要有主机、端口号(一般都会有密码，用户名可能没有),下面的两个@Bean不需要写了
     * spring:
     *   redis:
     *     host: localhost
     *     port: 6379
     *     password: '123456'
     */
    @Bean
    public LettuceConnectionFactory redisConnectionFactory() {
        RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
        config.setHostName(redisConfigProperties.getHost());
        config.setPort(redisConfigProperties.getPort());
        config.setPassword(redisConfigProperties.getPassword());
        config.setDatabase(redisConfigProperties.getDatabase());
        return new LettuceConnectionFactory(config);
    }
}
